# -*- coding: utf-8 -*-
"""
Created on Wed Oct  6 10:42:14 2021

@author: Bruind
"""
import tkinter
import time
import zipfile
import os as os

import win32com.client as win32
import pandas as pd
import xlrd



def Fun():
    global list_dir
    while True:
        filepath = input("请输入路径文件夹:") + "\\"
        if len(filepath) <= 1:
            print("请输入内容！")
            continue
        try:
            list_dir = os.listdir(filepath)
            break
        except FileNotFoundError as e:
            print("路径异常！请重新输入！")
            continue
    while True:
        head = input("请输入表头行（从0开始,通管局0）：")
        # print(len(head))
        if len(head) < 1:
            print("请输入内容！")
            continue
        try:
            head = int(head)
            break
        except ValueError:
            print("输入异常！请重新输入！")
            continue
    password = str(input('请输入密码（如果无请回车）：'))
    print('')
    statTime = int(time.time() * 1000)
    print('#################  开始处理 ' + time.strftime("%Y-%m-%d %H:%M:%S",
                                                     time.localtime()) + ' #########################\n')
    to_data_list = []
    to_excel_list = []
    list1 = []
    list2 = []
    mtime = []
    type_list = []
    passFile = []
    errFile = []
    zfCount = 0
    index = 1  # 序号

    print('################################ 开始解压 ###############################')
    for fileName in list_dir:  # 对文件夹下文件进行遍历，挑选出zip文件
        if fileName.endswith('zip'):
            zf = zipfile.ZipFile(filepath + fileName)  # 读取zip中的文件
            zip_list = zf.namelist()  # 获得zip中文件名的list
            # print('zip_list ==  ' + str(zip_list))
            for f in zip_list:  # 遍历集合，进行逐个解压
                # print('zip_f  == ' + f)
                # print('file_path == ' + filepath)
                try:
                    zf.extract(f.encode().decode('utf-8'), filepath,
                               pwd=password.encode('utf-8'))  # 参数一：文件 参数二：指定目录 参数三：密码
                    zfCount += 1
                except RuntimeError:
                    errFile.append(fileName)
                    continue
                finally:
                    zf.close()
            print('## ' + str(index) + ' 处理完毕 ##  ' + fileName)
            index += 1
    print('############################# 解压成功 :' + str(zfCount) + '个 #############################\n')
    fileList = os.listdir(filepath)
    print('####################  开始统计 ' + time.strftime("%Y-%m-%d %H:%M:%S",
                                                        time.localtime()) + ' ######################')
    index1 = 0
    for file in fileList:
        rowSum = 0
        data_path = filepath + file  # 此处为excel表的路径
        # fl = file.split('-')

        if not file.endswith('xlsx') and not file.endswith("xls") and not file.endswith('csv') and not file.endswith(
                'zip'):
            passFile.append(file)
            continue

        if file.endswith('csv'):  # 判断表格如果是否为csv格式
            filename = open(data_path)
            csvData = pd.read_csv(filename, header=head, iterator=True)  # 读取csv格式表格
            for index in range(300):  # 对表格进行分批次统计数据量
                try:
                    CsvSum = csvData.get_chunk(10000)  # 每次获取10000行
                    rowSum = rowSum + CsvSum.shape[0]  # 将行数进行累加
                except StopIteration:
                    break
                except Exception:
                    errFile.append(file)
            list1.append(file)
            list2.append(rowSum)
            mtime.append(get_update_time(data_path))
            type_list.append(get_type_list(file))
        elif file.endswith('xlsx') or file.endswith('xls'):  # 对xls和xlsx文件格式的表格进行处理
            try:
                data = pd.read_excel(data_path, header=head, sheet_name=0)  # 对表格进行直接读取转为pd对象
            except xlrd.biffh.XLRDError:  # 如果错误，则使用加密方式进行读取
                try:
                    data = df_from_pswxlsx(filename=data_path, password=password, header=head,  # 对加密excel进行密码校验并返回pd对象
                                           gl_excel_com='KET.Application',
                                           sheetIndex=1)
                    to_data_list.append(data)  # 将解密读取到的pd对象存入集合
                    to_excel_list.append(data_path)  # 将文件的输出路径及名字添加到集合
                except Exception as e:  # 如果异常则跳过该文件
                    errFile.append(file)
                    print(e)
                    continue
            rowSum = data.shape[0]  # 获取pd对象的数据条数
            list1.append(file)  # 对处理后的文件名添加入集合
            list2.append(rowSum)  # 对处理后的表格文件条数加入集合
            mtime.append(get_update_time(data_path))  # 对表格的更新时间加入集合
            type_list.append(get_type_list(file))  # 将文件类型加入集合
        else:
            continue
        index1 += 1
        print('##  ' + str(index1) + '\t处理完毕 ##  \t' + file)
    Current_time = time.strftime("%Y%m%d_", time.localtime())
    for i in range(0, len(to_data_list)):  # 将解密后的pd对象内容进行遍历
        try:
            pd.DataFrame(to_data_list[i]).to_excel(to_excel_list[i], index=False, header=True)  # 对解密后的pd对象进行输出为文件
        except Exception as e:
            print(e)
    endTime = int(time.time() * 1000)
    print('#######################################################################\n')
    print('############################# 跳过文件 :' + str(len(passFile)) + '个 #############################')
    index = 1
    for pf in passFile:
        print('## ' + str(index) + ' 跳过  \t##   ' + pf)
        index += 1
    print('#######################################################################\n')
    print('############################# 错误文件 :' + str(len(errFile)) + '个 #############################')
    index = 1
    if len(errFile) != 0:
        for ef in errFile:
            print('## ' + str(index) + ' 错误  \t## >  ' + ef)
            index += 1
    print('#######################################################################\n')
    print('#################  处理完毕 ' + time.strftime("%Y-%m-%d",
                                                     time.localtime()) + ' #########################')
    print('##  统计有效文件个数：' + str(len(list1)) + '个，统计总用时：' + str(endTime - statTime) + '毫秒！')
    outFileName = filepath + Current_time + '统计数据量.xlsx'
    Excel = {'文件类型': type_list,
             '名': list1,
             '数量': list2,
             '修改时间': mtime
             }

    te = pd.DataFrame(Excel)
    if list1 or list2:
        if os.path.exists(outFileName):  # 判断该统计数据量文件是否存在
            ed = pd.DataFrame(pd.read_excel(outFileName))  # 如果存在将该问价加载入内存进行读取
            # new_excel = openFile(ed, list2, list1)
            former_excel = new_excel(ed, te)  # 判断新集合中适合包好原有相同名文件,并返回不包含文件
            list1.append(former_excel[0])  # 将新文件名存入原统计excel中
            list2.append(former_excel[1])  # 将新表格的文件条数存入新list中
            te.to_excel(outFileName, header=True, index=False)  # 对pd对象进行输出为xlsx
        else:
            te.to_excel(outFileName, header=True, index=False)  # 对未存在统计过的文件进行直接输出xlsx
        print('##  已完成,数据量输出在 ====>  ' + outFileName)
        input("请输入回车打开文件或者直接关闭！")
        os.system(outFileName)
    else:
        input("请输入回车或者直接关闭！")


def df_from_pswxlsx(filename, password, gl_excel_com, header, sheetIndex):
    """
    调用格式：
    df=df_from_pswxlsx("D://amlui//pivot//aa.xlsx","Xyl19765225","KET.Application")
    参数一：文件路径
    参数二：文件密码
    参数三：不同配置的Excel-COM 参数，WPS excel用'KET.Application',
            MS office Excel文件用'Excel.Application'
    参数四：excel工作簿中要处理的sheet名。
    return: 解密后输出的pandas格式的df，df就可以参与各种运算了。
    """
    psw_xlsx = win32.DispatchEx(gl_excel_com)  # 这个功能创建新进程，不会打扰用户手动进程
    psw_xlsx.DisplayAlerts = 0  # 不显示警告,SaveAS的弹框就不出来了。
    wb = None
    try:
        wb = psw_xlsx.Workbooks.Open(filename, UpdateLinks=False, ReadOnly=False, Format=None, Password=password,
                                     WriteResPassword=password)
        # 获取工作表具体情况
        data_lst = list(wb.Worksheets(sheetIndex).UsedRange())  # 数据存入,"原始数据"，2-"借贷求和计数"...数字与表名可以互换
        df = pd.DataFrame(data_lst[1:],
                          columns=data_lst[header])  # data_lst[1:]除了表头（只有一行）以外的所有数据，data_lst[0],原excel表的第一行表头作为列索引。
        wb.Close()
        psw_xlsx.DisplayAlerts = 1
        psw_xlsx.Application.Quit()  # 只清掉我自己开启的进程
        return df
    finally:
        psw_xlsx.Application.Quit()



def get_type_list(file):
    '''
    判断表格的文件类型
    :param file: 判断的文件
    :return: 文件类型str
    '''
    if file.lower().startswith('skbs'):
        return '时空伴随'
    elif file.lower().startswith('zdqy'):
        return '重点区域'
    elif file.lower().startswith('sm'):
        return '省漫'
    else:
        return '其他'


def get_update_time(file_path):
    '''
    获取文件的修改时间
    :param file_path: 文件路径
    :return: 返回文件修改时间的str
    '''
    mtime = os.stat(file_path).st_mtime
    return time.strftime('%Y-%m-%d %H:%M', time.localtime(mtime))


def new_excel(excel, new_excel):
    '''
    对老表格数据与新统计文件按名字进行比对
    :param excel: 老表格pd对象
    :param new_excel: 新表格pd对象
    :return: 不相同文件名及数据量结果集
    '''
    name_list = []
    count_list = []
    list = []
    # print(new_excel.loc[2:1])
    excel_count_list = excel['数量']
    excel_name_list = excel['名']
    new_excel_name_list = new_excel['名']
    for i in range(0, len(excel_name_list)):
        if excel_name_list[i] not in new_excel_name_list:
            name_list.append(excel_name_list[i])
            count_list.append(excel_count_list[i])
        else:
            continue
    list.append(name_list)
    list.append(count_list)
    return list


if __name__ == '__main__':
    # top = tkinter.Tk()
    # top.mainloop()
    Fun()
    # l = ['Python', 'C++', 'Java']
    #
    # # 插入元素
    #
    # l.insert(0, 'C')
    #
    # print(l)
